package toy.keli.picmap.model;

import android.text.TextUtils;

import androidx.annotation.NonNull;

import java.util.Iterator;
import java.util.Map;

public class Model {
    public int id=0;
    private String _table;
    protected def _data;
    private String tableName(){
        if(_table!=null) return _table;
        String tabName=this.getClass().getCanonicalName();
        String[] a=tabName.split("\\.");
        return _table=a[a.length-1];
    }
    Model(){}
    Model(int id){
        this.id=id;
        findOne("id="+id);
    }
    public boolean save(){
        String tabName=tableName();
        if(id != 0){
            Map<String, String> maps = def.valueOf(this).toHash();
            String[] attrs = new String[maps.size()];
            int i=0;
            for(String k : maps.keySet()){
                String v=maps.get(k);
                if(k.equals("uptime")) v= String.valueOf(System.currentTimeMillis());
                attrs[i++]=k+"='"+v+"'";
            }
            //TextUtils  https://www.javaer101.com/article/1452130.html
            db.execute("update "+tabName+" set "+ TextUtils.join(",",attrs) +" where id="+id,null);
            return true;
        }

        Map<String, String> params = def.valueOf(this).toHash();
        if(params.size()==0){
            log.Waring("insert data empty!");
            return false;
        }
        String[] keys=new String[params.size()];
        String [] values=new String[params.size()];
        int i=0;
        for(String k : params.keySet()){
            String v=params.get(k);
            if(k.equals("intime") && v==null) v=String.valueOf(System.currentTimeMillis());
            else if(k.equals("uptime")) v= String.valueOf(System.currentTimeMillis());
            keys[i]=String.format("`%s`",k);
            values[i]=String.format("'%s'",v);
            i++;
        }
        String sql=String.format("insert into `%s` (%s) values (%s)",tabName,TextUtils.join(",",keys),TextUtils.join(",",values));
        id=db.execute(sql,null);

        return true;
    }

    //https://www.cnblogs.com/jingle1267/archive/2012/12/04/2801262.html
    public iterator findAll() {
        return findAll("1=1");
    }
    public iterator findAll(String where) {
//        String tableName=new Throwable().getStackTrace()[2].getClassName();
//        return db.query(tableName,where);
        def datas=find().where(where).all();
        return new iterator(datas,this.getClass());
    }

    public db.Query find(){
        //return new Query(this);
        return db.find(tableName());
    }

    public void setAttributs(def fInfo) {
        fInfo.toObject(this);
    }

    class Query extends  db.Query{
        Model myModel;
        public Query(Model c) {
            myModel=c;
            setTableName(c.tableName());
        }
        public Model One() {
            def data = super.one();
            myModel.setData(data);
            return myModel;
        }

        public iterator All() {
            def datas = super.all();
            return new iterator(datas,myModel.getClass());
        }
    }
    public Model findOne(String where){
        setData(find().where(where).order("id desc").one());
        return this;
    }

    public Model findOne() {
        setData(find().order("id desc").one());
        return this;
    }
    public void setData(def data){
        _data=data;
        _data.toObject(this);
    }

    public static Model populateRecord(Class tableClass, def data) {
        Model rt= null;
        try {
            rt = (Model)Class.forName(tableClass.getCanonicalName()).newInstance();
            rt.setData(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return rt;
    }


    public static class iterator  implements Iterable<Model>,Iterator {
        def datas;
        Class tableClass;
        public iterator(def res,Class c) {
            datas=res;
            tableClass=c;
        }

        @NonNull
        @Override
        public Iterator<Model> iterator() {
            return this;
        }

        @Override
        public boolean hasNext() {
            return datas.hasNext();
        }

        @Override
        public Model next() {
            return Model.populateRecord(tableClass,(def)datas.next());
        }

        public def toDef() {
            def rt=new def();
            for(Model m : this){
                rt.push(m);
            }
            return rt;
        }
    }


    public boolean remove(){
        return find().where("id="+id).delete()>0;
    }

}
